//
// Created by juno on 2021/9/12.
//

#include "room.h"
#include "member.h"
#include "message.h"
#include "common.h"

static unsigned int membase_id = 0;
static struct member_t *members = NULL;

static int member_insert(struct member_t *member)
{
    struct member_t *curr = members;
    struct member_t *next = NULL;

    if (members == NULL)
        members = member;
    else {
        do {
            next = curr->next;

            if (next)
                curr = next;
        }while(next);

        curr->next = member;
    }

    return 0;
}

int member_new(struct member_base_info *base, struct member_t **res)
{
    struct member_base_info *info = calloc(1, sizeof(struct member_base_info));
    struct member_t *member = calloc(1, sizeof(struct member_t));

    if (!info)
        return -1;

    if (!member)
    {
        free(info);
        return -1;
    }

    info->name = strdup(base->name);
    info->uuid = base->uuid;
    info->id = membase_id;
    membase_id ++;

    member->base = info;
    member->next = NULL;
    member->room = NULL;

    *res = member;

    member_insert(member);

    return 0;
}

int member_create_room(struct member_t *member, char *name, struct room_t **res)
{
    struct room_t *room = room_find_by_name(name);
    struct room_info info = {0};
    char *uuid = NULL;

    if (room)
        return -ROOM_ERR_CODE_EXIST;

    if (gen_token(&uuid) < 0)
        return -ROOM_ERR_CODE_UUID;

    info.owner = member;
    info.uuid = uuid;
    info.name = name;

    if (room_new(&info, &room) < 0)
        return -ROOM_ERR_CODE_NOMEM;

    if (res)
        *res = room;

    return 0;

}

int member_join_room(struct member_t *member, const char *name)
{
    struct room_t *room = room_find_by_name(name);
    struct member_t *cur = NULL;
    struct member_t *next = NULL;

    if (!room)
        return -ROOM_ERR_CODE_NOEXIST;

    cur = room->member;

    do {
        next = cur->next;
        if (next)
            cur = next;
    }while(next);

    cur->next = member;
    member->room = room;

    return 0;
}

int member_leave_room(struct member_t *member)
{
    if (!member)
        return -EINVAL;

    struct room_t *room = member->room;
    struct member_t *next = NULL;
    struct member_t *prev = NULL;
    struct member_t *curr = room->member;

    if (member == room->info->owner)
    {
        room_destroy(room);
        return 0;
    } else {
        do {
            next = curr->next;
            if (member == curr)
            {
                if (next)
                {
                    if (prev) {
                        prev->next = next;
                        break;
                    } else {
                        room->member = next;
                        break;
                    }
                } else {
                    if (prev)
                        room->member = prev;
                    else
                        room_destroy(room);
                    break;
                }
            } else {
                prev = curr;
                curr = next;
            }
        }while(curr);
    }

    member->room = NULL;

    return  0;

}

void member_destroy(struct member_t *member)
{
    struct room_t *room = member->room;
    struct member_t *curr = room->member;
    struct member_t *next = NULL;
    struct member_t *prev = NULL;

    if (room->info->owner == member)
    {
        room_destroy(room);
        return;
    }

    do {
        next = curr->next;
        if (curr == member)
        {
            if (next)
            {
                if (prev)
                    prev->next = next;
                else
                    room->member = next;
            } else {
                if (!prev)
                    room_destroy(room);
            }
            break;
        }
        prev = curr;
        curr = next;
    }while(curr);
}

int member_change_room(struct member_t *member, const char *name)
{
    member_leave_room(member);

    return member_join_room(member, name);
}
